package com.example.aiquestions.service.impl;

import com.example.aiquestions.config.AIConfig;
import com.example.aiquestions.model.dto.ChatRequest;
import com.example.aiquestions.model.dto.ChatResponse;
import com.example.aiquestions.model.dto.Message;
import com.example.aiquestions.service.AIService;
import com.example.aiquestions.service.StreamResponseHandler;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class QianwenServiceImpl implements AIService {

    @Autowired
    private AIConfig aiConfig;

    private final OkHttpClient client;
    private final ObjectMapper objectMapper;

    // 使用与DeepseekServiceImpl相同的提示词
    private static final String SINGLE_CHOICE_PROMPT = DeepseekServiceImpl.SINGLE_CHOICE_PROMPT;
    private static final String MULTIPLE_CHOICE_PROMPT = DeepseekServiceImpl.MULTIPLE_CHOICE_PROMPT;
    private static final String SHORT_ANSWER_PROMPT = DeepseekServiceImpl.SHORT_ANSWER_PROMPT;
    private static final String TRUE_FALSE_PROMPT = DeepseekServiceImpl.TRUE_FALSE_PROMPT;
    private static final String FILL_BLANK_PROMPT = DeepseekServiceImpl.FILL_BLANK_PROMPT;
    private static final String READING_PROMPT = DeepseekServiceImpl.READING_PROMPT;
    public static final String ALL_PROMPTS = DeepseekServiceImpl.ALL_PROMPTS;

    public QianwenServiceImpl() {
        this.client = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                .build();
        this.objectMapper = new ObjectMapper();
    }

    @Override
    public ChatResponse chat(ChatRequest request) {
        try {
            String jsonRequest = objectMapper.writeValueAsString(request);
            RequestBody body = RequestBody.create(
                    jsonRequest,
                    MediaType.parse("application/json; charset=utf-8")
            );

            Request httpRequest = new Request.Builder()
                    .url(aiConfig.getQianwen().getApiUrl())
                    .addHeader("Authorization", "Bearer " + aiConfig.getQianwen().getApiKey())
                    .post(body)
                    .build();

            try (Response response = client.newCall(httpRequest).execute()) {
                if (!response.isSuccessful()) {
                    throw new IOException("Unexpected response code: " + response);
                }

                String responseBody = response.body().string();
                return objectMapper.readValue(responseBody, ChatResponse.class);
            }
        } catch (Exception e) {
            throw new RuntimeException("Failed to chat with Qianwen API", e);
        }
    }

    @Override
    public ChatResponse generateQuestion(String userPrompt) {
        ChatRequest request = new ChatRequest();
        request.setModel(aiConfig.getQianwen().getModel());
        request.setTemperature(aiConfig.getQianwen().getTemperature());
        request.setMaxTokens(aiConfig.getQianwen().getMaxTokens());
        request.setStream(aiConfig.getQianwen().getStream());

//        // 根据题型选择对应的提示词
//        String prompt = switch (questionType.toUpperCase()) {
//            case "SINGLE_CHOICE" -> SINGLE_CHOICE_PROMPT;
//            case "MULTIPLE_CHOICE" -> MULTIPLE_CHOICE_PROMPT;
//            case "SHORT_ANSWER" -> SHORT_ANSWER_PROMPT;
//            case "TRUE_FALSE" -> TRUE_FALSE_PROMPT;
//            case "FILL_BLANK" -> FILL_BLANK_PROMPT;
//            case "READING" -> READING_PROMPT;
//            default -> throw new IllegalArgumentException("Unsupported question type: " + questionType);
//        };

        // 添加系统提示词和用户消息
        Message systemMessage = new Message("system", ALL_PROMPTS);
        Message userMessage = new Message("user", userPrompt);
        request.setMessages(Arrays.asList(systemMessage, userMessage));

        return chat(request);
    }

    public ChatResponse generateGraphData(String userPrompt) {
        ChatRequest request = new ChatRequest();
        request.setModel(aiConfig.getDeepseek().getModel());
        request.setTemperature(aiConfig.getDeepseek().getTemperature());
        request.setMaxTokens(aiConfig.getDeepseek().getMaxTokens());
        request.setStream(aiConfig.getDeepseek().getStream());

        String systemPrompt = """
        你是一个专业的知识图谱生成助手。请根据用户输入的知识点内容，生成结构化的知识图谱数据。
        
        你需要从用户输入的文本中提取关键知识点，并将它们组织成如下JSON格式：
        [
          {
            "chapter": 章节号(整数),
            "node": 某一章节下的某一节(整数),
            "knowledge": "具体知识点名称",
            "mastery": "掌握程度(理解/掌握/应用/了解中的一种)",
            "difficulty": 难度系数(1-3的整数，3表示最难)
          },
          ...
        ]
        
        请注意以下几点：
        1. 章节号(chapter)表示大的知识模块，按照内容逻辑顺序从1开始编号
        2. 节点号(node)表示同一章节下不同的小节，例如第一章第一节，第一章第二节等等
        3. 相关的知识点应该属于同一章节，可以是同一节点或不同节点
        4. 掌握程度(mastery)根据知识点的学习要求，选择"理解"、"掌握"、"应用"或"了解"
        5. 难度系数(difficulty)根据知识点的复杂程度，从1到3评级
        
        请确保生成的JSON格式正确，且每个知识点都有合理的章节号、节点号、掌握程度和难度系数。
        不要添加任何额外的解释，直接输出有效的JSON数据。
        """;

        // 添加系统提示词和用户消息
        Message systemMessage = new Message("system", systemPrompt);
        Message userMessage = new Message("user", userPrompt);
        request.setMessages(Arrays.asList(systemMessage, userMessage));

        try {
            return chat(request);
        } catch (Exception e) {
            System.err.println("Error in generateGraphData: " + e.getMessage());
            e.printStackTrace();

            // 尝试直接通过HTTP请求获取结果并手动解析
            try {
                String jsonRequest = objectMapper.writeValueAsString(request);
                RequestBody body = RequestBody.create(
                        MediaType.parse("application/json; charset=utf-8"),
                        jsonRequest
                );

                Request httpRequest = new Request.Builder()
                        .url(aiConfig.getDeepseek().getApiUrl())
                        .addHeader("Authorization", "Bearer " + aiConfig.getDeepseek().getApiKey())
                        .post(body)
                        .build();

                try (Response response = client.newCall(httpRequest).execute()) {
                    if (!response.isSuccessful()) {
                        throw new IOException("Unexpected response code: " + response);
                    }

                    // 获取响应体并手动提取content字段
                    String responseBody = response.body().string();
                    System.out.println("API Raw Response: " + responseBody);

                    // 创建一个简化版的ChatResponse对象
                    ChatResponse chatResponse = new ChatResponse();

                    JsonObject jsonObject = JsonParser.parseString(responseBody).getAsJsonObject();
                    JsonArray choices = jsonObject.getAsJsonArray("choices");
                    if (choices != null && choices.size() > 0) {
                        JsonObject messageObj = choices.get(0).getAsJsonObject()
                                .getAsJsonObject("message");
                        if (messageObj != null && messageObj.has("content")) {
                            String content = messageObj.get("content").getAsString();

                            List<ChatResponse.Choice> choiceList = new ArrayList<>();
                            ChatResponse.Choice choice = new ChatResponse.Choice();
                            Message message = new Message("assistant", content);
                            choice.setMessage(message);
                            choiceList.add(choice);

                            chatResponse.setChoices(choiceList);
                            return chatResponse;
                        }
                    }

                    throw new IOException("Failed to extract content from response");
                }
            } catch (Exception ex) {
                System.err.println("Error in fallback method: " + ex.getMessage());
                ex.printStackTrace();
                throw new RuntimeException("Failed to generate graph data", ex);
            }
        }
    }
    @Override
    public ChatResponse sendMessage(String message) {
        return generateQuestion(message); // 默认生成单选题
    }

    @Override
    public String getProvider() {
        return "qianwen";
    }

    @Override
    public void generateQuestionStream(String prompt, StreamResponseHandler handler) {
        try {
            OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(120, TimeUnit.SECONDS)  // 增加超时时间
                .writeTimeout(120, TimeUnit.SECONDS)
                .readTimeout(120, TimeUnit.SECONDS)
                .build();

            // 构建 QianWen 的请求体
            JsonObject jsonRequest = new JsonObject();
            jsonRequest.addProperty("model", aiConfig.getQianwen().getModel());
            
            // 构建messages数组
            JsonArray messagesArray = new JsonArray();
            JsonObject systemMessage = new JsonObject();
            systemMessage.addProperty("role", "system");
            systemMessage.addProperty("content", ALL_PROMPTS);
            messagesArray.add(systemMessage);
            
            JsonObject userMessage = new JsonObject();
            userMessage.addProperty("role", "user");
            userMessage.addProperty("content", prompt);
            messagesArray.add(userMessage);
            
            jsonRequest.add("messages", messagesArray);
            jsonRequest.addProperty("stream", true);
            jsonRequest.addProperty("temperature", aiConfig.getQianwen().getTemperature());
            jsonRequest.addProperty("max_tokens", aiConfig.getQianwen().getMaxTokens());

            RequestBody requestBody = RequestBody.create(
                MediaType.parse("application/json"),
                jsonRequest.toString()
            );

            // 使用流式API URL
            String apiUrl = aiConfig.getQianwen().getStreamApiUrl();
            if (apiUrl == null) {
                apiUrl = aiConfig.getQianwen().getApiUrl() + "/stream";
            }

            Request request = new Request.Builder()
                .url(apiUrl)
                .post(requestBody)
                .addHeader("Authorization", "Bearer " + aiConfig.getQianwen().getApiKey())
                .build();

            client.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    System.err.println("Stream request failed: " + e.getMessage());
                    handler.onError(e);
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    if (!response.isSuccessful()) {
                        String errorBody = response.body() != null ? response.body().string() : "No error body";
                        System.err.println("Unexpected response: " + response.code() + ", Error: " + errorBody);
                        handler.onError(new IOException("Unexpected code " + response + ", Error: " + errorBody));
                        return;
                    }

                    try (ResponseBody responseBody = response.body()) {
                        if (responseBody == null) {
                            System.err.println("Response body is null");
                            handler.onError(new IOException("Response body is null"));
                            return;
                        }

                        BufferedReader reader = new BufferedReader(
                            new InputStreamReader(responseBody.byteStream())
                        );

                        String line;
                        StringBuilder currentQuestion = new StringBuilder();
                        boolean isCollectingQuestion = false;
                        int braceCount = 0;  // 用于跟踪大括号的嵌套层级
                        
                        while ((line = reader.readLine()) != null) {
                            if (line.startsWith("data: ")) {
                                String data = line.substring(6).trim();
                                if (data.equals("[DONE]")) {
                                    // 处理最后可能剩余的数据
                                    if (currentQuestion.length() > 0) {
                                        String questionJson = currentQuestion.toString().trim();
                                        if (questionJson.startsWith("{") && questionJson.endsWith("}")) {
                                            processCompleteQuestion(questionJson, handler);
                                        }
                                    }
                                    handler.onComplete();
                                    break;
                                }
                                
                                try {
                                    JsonObject jsonResponse = JsonParser.parseString(data)
                                        .getAsJsonObject();
                                    JsonArray choices = jsonResponse.getAsJsonArray("choices");
                                    if (choices != null && choices.size() > 0) {
                                        JsonObject delta = choices.get(0).getAsJsonObject()
                                            .getAsJsonObject("delta");
                                        if (delta != null && delta.has("content")) {
                                            String content = delta.get("content").getAsString();
                                            if (content != null && !content.isEmpty()) {
                                                // 移除markdown标记
                                                content = content.replace("```json", "")
                                                               .replace("```", "");
                                                
                                                // 处理每个字符
                                                for (char c : content.toCharArray()) {
                                                    if (c == '{') {
                                                        if (!isCollectingQuestion) {
                                                            isCollectingQuestion = true;
                                                            currentQuestion.setLength(0);
                                                        }
                                                        braceCount++;
                                                    }
                                                    
                                                    if (isCollectingQuestion) {
                                                        currentQuestion.append(c);
                                                    }
                                                    
                                                    if (c == '}') {
                                                        braceCount--;
                                                        // 检测到一个完整的题目
                                                        if (braceCount == 0 && isCollectingQuestion) {
                                                            String questionJson = currentQuestion.toString().trim();
                                                            processCompleteQuestion(questionJson, handler);
                                                            // 重置状态
                                                            currentQuestion.setLength(0);
                                                            isCollectingQuestion = false;
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                } catch (Exception e) {
                                    System.err.println("Error parsing chunk: " + data);
                                    e.printStackTrace();
                                    continue;
                                }
                            }
                        }
                    } catch (Exception e) {
                        System.err.println("Error processing response: " + e.getMessage());
                        e.printStackTrace();
                        handler.onError(e);
                    }
                }
            });
        } catch (Exception e) {
            System.err.println("Error initiating stream request: " + e.getMessage());
            e.printStackTrace();
            handler.onError(e);
        }
    }

    private void processCompleteQuestion(String questionJson, StreamResponseHandler handler) {
        try {
            // 验证JSON格式
            JsonObject questionObj = JsonParser.parseString(questionJson).getAsJsonObject();
            /**
             * 验证太麻烦先去掉了
             */
//            if (validateQuestionFormat(questionObj)) {
                // 将单个题目包装成数组格式
                handler.onNext("[" + questionJson + "]");
//            } else {
//                System.err.println("Invalid question format: " + questionJson);
//            }
        } catch (Exception e) {
            System.err.println("Invalid question JSON: " + e.getMessage());
        }
    }

    private String extractJsonFromText(String text) {
        // 提取JSON字符串
        int startIndex = text.indexOf("{");
        int endIndex = text.lastIndexOf("}") + 1;
        if (startIndex >= 0 && endIndex > startIndex) {
            return text.substring(startIndex, endIndex);
        }
        return null;
    }

    private boolean validateQuestionFormat(JsonObject question) {
        try {
            // 验证必要字段
            boolean hasRequiredFields = question.has("questionType") && 
                                      question.has("stem") && 
                                      (question.has("answer") || question.has("answers")) &&
                                      question.has("difficulty");
            
            if (!hasRequiredFields) {
                return false;
            }
            
            // 验证题目类型
            String type = question.get("questionType").getAsString();
            return type.equals("SINGLE_CHOICE") || 
                   type.equals("MULTIPLE_CHOICE") || 
                   type.equals("SHORT_ANSWER") || 
                   type.equals("TRUE_FALSE") || 
                   type.equals("FILL_BLANK") ||
                   type.equals("READING");
        } catch (Exception e) {
            System.err.println("Error validating question format: " + e.getMessage());
            return false;
        }
    }

    /**
     * 使用流式API生成知识图谱数据
     * 
     * @param userPrompt 用户输入的提示词
     * @param handler 流式响应处理器
     */
    @Override
    public void generateGraphDataStream(String userPrompt, StreamResponseHandler handler) {
        try {
            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(120, TimeUnit.SECONDS)  // 增加超时时间
                    .writeTimeout(120, TimeUnit.SECONDS)
                    .readTimeout(120, TimeUnit.SECONDS)
                    .build();

            // 构建请求体
            JsonObject jsonRequest = new JsonObject();
            jsonRequest.addProperty("model", aiConfig.getQianwen().getModel());

            // 构建messages数组
            JsonArray messagesArray = new JsonArray();
            JsonObject systemMessage = new JsonObject();
            systemMessage.addProperty("role", "system");
            systemMessage.addProperty("content", """
            你是一个专业的知识图谱生成助手。请根据用户输入的知识点内容，生成结构化的知识图谱数据。
            
            你需要从用户输入的文本中提取关键知识点，并将它们组织成如下JSON格式：
            [
              {
                "chapter": 章节号(整数),
                "node": 某一章节下的某一节(整数),
                "knowledge": "具体知识点名称",
                "mastery": "掌握程度(理解/掌握/应用/了解中的一种)",
                "difficulty": 难度系数(1-3的整数，3表示最难)
              },
              ...
            ]
            
            请注意以下几点：
            1. 章节号(chapter)表示大的知识模块，按照内容逻辑顺序从1开始编号
            2. 节点号(node)表示同一章节下不同的小节，例如第一章第一节，第一章第二节等等
            3. 相关的知识点应该属于同一章节，可以是同一节点或不同节点
            4. 掌握程度(mastery)根据知识点的学习要求，选择"理解"、"掌握"、"应用"或"了解"
            5. 难度系数(difficulty)根据知识点的复杂程度，从1到3评级
            
            请确保生成的JSON格式正确，且每个知识点都有合理的章节号、节点号、掌握程度和难度系数。
            不要添加任何额外的解释，直接输出有效的JSON数据。
            """);
            messagesArray.add(systemMessage);

            JsonObject userMessageObj = new JsonObject();
            userMessageObj.addProperty("role", "user");
            userMessageObj.addProperty("content", userPrompt);
            messagesArray.add(userMessageObj);

            jsonRequest.add("messages", messagesArray);
            jsonRequest.addProperty("stream", true);
            jsonRequest.addProperty("temperature", aiConfig.getQianwen().getTemperature());
            jsonRequest.addProperty("max_tokens", aiConfig.getQianwen().getMaxTokens());

            RequestBody requestBody = RequestBody.create(
                    MediaType.parse("application/json"),
                    jsonRequest.toString()
            );

            // 使用流式API URL
            String apiUrl = aiConfig.getQianwen().getStreamApiUrl();
            if (apiUrl == null) {
                apiUrl = aiConfig.getQianwen().getApiUrl();
            }

            Request request = new Request.Builder()
                    .url(apiUrl)
                    .post(requestBody)
                    .addHeader("Authorization", "Bearer " + aiConfig.getQianwen().getApiKey())
                    .build();

            client.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    System.err.println("Stream request failed: " + e.getMessage());
                    handler.onError(e);
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    if (!response.isSuccessful()) {
                        String errorBody = response.body() != null ? response.body().string() : "No error body";
                        System.err.println("Unexpected response: " + response.code() + ", Error: " + errorBody);
                        handler.onError(new IOException("Unexpected code " + response + ", Error: " + errorBody));
                        return;
                    }

                    try (ResponseBody responseBody = response.body()) {
                        if (responseBody == null) {
                            System.err.println("Response body is null");
                            handler.onError(new IOException("Response body is null"));
                            return;
                        }

                        BufferedReader reader = new BufferedReader(
                                new InputStreamReader(responseBody.byteStream())
                        );

                        // 用于收集完整的JSON响应
                        StringBuilder fullJsonResponse = new StringBuilder();
                        StringBuilder currentChunk = new StringBuilder();
                        int openBrackets = 0;
                        int closeBrackets = 0;
                        boolean isCollecting = false;

                        String line;
                        while ((line = reader.readLine()) != null) {
                            if (line.startsWith("data: ")) {
                                String data = line.substring(6).trim();
                                
                                // 流的结束标志
                                if (data.equals("[DONE]")) {
                                    // 处理可能剩余的数据
                                    String finalJson = cleanAndCompleteJson(fullJsonResponse.toString());
                                    if (isValidJson(finalJson)) {
                                        handler.onNext(finalJson);
                                    }
                                    handler.onComplete();
                                    break;
                                }

                                try {
                                    // 解析流的数据部分
                                    JsonObject jsonResponse = JsonParser.parseString(data)
                                            .getAsJsonObject();
                                    JsonArray choices = jsonResponse.getAsJsonArray("choices");
                                    
                                    if (choices != null && choices.size() > 0) {
                                        JsonObject delta = choices.get(0).getAsJsonObject()
                                                .getAsJsonObject("delta");
                                        
                                        if (delta != null && delta.has("content")) {
                                            String content = delta.get("content").getAsString();
                                            if (content != null && !content.isEmpty()) {
                                                // 移除markdown格式标记
                                                content = content.replace("```json", "")
                                                        .replace("```", "");
                                                
                                                currentChunk.append(content);
                                                
                                                // 跟踪括号以检测JSON数组的开始和结束
                                                for (char c : content.toCharArray()) {
                                                    if (c == '[') {
                                                        isCollecting = true;
                                                        openBrackets++;
                                                    } else if (c == ']') {
                                                        closeBrackets++;
                                                    }
                                                }
                                                
                                                // 检查是否有完整的JSON数组
                                                if (isCollecting && openBrackets > 0 && openBrackets == closeBrackets) {
                                                    // 找到完整的JSON数组
                                                    String chunk = currentChunk.toString().trim();
                                                    fullJsonResponse.append(chunk);
                                                    
                                                    // 重置变量，为下一个JSON数组做准备
                                                    currentChunk.setLength(0);
                                                    openBrackets = 0;
                                                    closeBrackets = 0;
                                                    isCollecting = false;
                                                }
                                            }
                                        }
                                    }
                                } catch (Exception e) {
                                    System.err.println("Error parsing chunk: " + data);
                                    e.printStackTrace();
                                }
                            }
                        }
                    } catch (Exception e) {
                        System.err.println("Error processing response: " + e.getMessage());
                        e.printStackTrace();
                        handler.onError(e);
                    }
                }
            });
        } catch (Exception e) {
            System.err.println("Error initiating stream request: " + e.getMessage());
            e.printStackTrace();
            handler.onError(e);
        }
    }

    /**
     * 清理和完成JSON字符串，确保其格式正确
     */
    private String cleanAndCompleteJson(String jsonString) {
        // 移除前后可能的非JSON字符
        jsonString = jsonString.trim();
        
        // 确保JSON数组以[开始，以]结束
        if (!jsonString.startsWith("[")) {
            jsonString = "[" + jsonString;
        }
        if (!jsonString.endsWith("]")) {
            jsonString += "]";
        }
        
        return jsonString;
    }

    /**
     * 验证JSON字符串是否有效
     */
    private boolean isValidJson(String jsonString) {
        try {
            JsonParser.parseString(jsonString);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
} 